/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.common.sdk.net.download.callback;

import java.util.List;
import java.util.concurrent.Executor;

import android.os.Handler;

import com.common.sdk.net.download.callback.error.CallbackEnum;
import com.common.sdk.net.download.callback.error.DownloadState;
import com.common.sdk.net.download.callback.interfaces.IDownloadCallback;
import com.common.sdk.net.download.callback.interfaces.IResponseDelivery;
import com.common.sdk.net.download.request.model.DownloadInfo;
import com.common.sdk.net.download.util.DownloadLog;

/**
 * Delivers responses and errors.
 */
public class ExecutorDelivery implements IResponseDelivery {
    /** Used for posting responses, typically to the main thread. */
    private final Executor mResponsePoster;

    /**
     * Creates a new response delivery interface.
     * @param handler {@link Handler} to post responses on
     */
    public ExecutorDelivery(final Handler handler) {
        // Make an Executor that just wraps the handler.
        mResponsePoster = new Executor() {
            @Override
            public void execute(Runnable command) {
                handler.post(command);
            }
        };
    }

    /**
     * Creates a new response delivery interface, mockable version
     * for testing.
     * @param executor For running delivery tasks
     */
    public ExecutorDelivery(Executor executor) {
        mResponsePoster = executor;
    }

    @Override
    public void postResponse(IDownloadCallback iDownloadCallback, int downloadFailedState, CallbackEnum callbackEnum,
                             DownloadInfo downloadInfo) {
        mResponsePoster.execute(new ResponseDeliveryRunnableItem(iDownloadCallback, downloadFailedState, callbackEnum,
                downloadInfo));
    }

    @Override
    public void postResponse(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum, DownloadInfo downloadInfo) {
        mResponsePoster.execute(new ResponseDeliveryRunnableEnumItem(iDownloadCallback, callbackEnum, downloadInfo));
    }

    @Override
    public void postResponse(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum, List<DownloadInfo> list) {
        mResponsePoster.execute(new ResponseDeliveryRunnableEnumList(iDownloadCallback, callbackEnum, list));
    }

    @Override
    public void postResponse(IDownloadCallback iDownloadCallback, int downloadFailedState, List<DownloadInfo> list) {
        // TODO Auto-generated method stub

    }

    /**
     * A Runnable used for delivering network responses to a listener on the
     * main thread.
     */
    private class ResponseDeliveryRunnableItem implements Runnable {

        private IDownloadCallback iDownloadCallback;
        private int downloadFailedState;
        private CallbackEnum callbackEnum;
        private DownloadInfo downloadInfo;

        public ResponseDeliveryRunnableItem(IDownloadCallback iDownloadCallback, int downloadFailedState,
                                            CallbackEnum callbackEnum, DownloadInfo downloadInfo) {
            this.iDownloadCallback = iDownloadCallback;
            this.downloadFailedState = downloadFailedState;
            this.callbackEnum = callbackEnum;
            this.downloadInfo = downloadInfo;
        }

        @Override
        public void run() {

            switch (callbackEnum) {
                case FAILED_DOWNLOAD:
                    int error = 0;
                    DownloadLog.error("Callback onFailedDownload : " + downloadFailedState);
                    switch (downloadFailedState) {
                        case DownloadState.NET_ERROR_UNKNOWN:
                        case DownloadState.NET_ERROR_NO_NET:
                        case DownloadState.NET_ERROR_DEFAULT_NET_FAILED:
                        case DownloadState.NET_ERROR_DOWNLOAD_IOEXCEPTION:
                        case DownloadState.NET_ERROR_DOWNLOAD_FILE_IOEXCEPTION:
                        case DownloadState.NET_ERROR_DOWNLOAD_INIT_EXCEPTION:
                        case DownloadState.NET_ERROR_DOWNLOAD_CLOSE_FILE_IO_EXCEPTION:
                            error = DownloadState.NET_ERROR;
                            break;
                        case DownloadState.DATABASE_ERROR_DELETE_FILE:
                            error = DownloadState.DATABASE_ERROR;
                            break;
                        case DownloadState.SD_NO_SPACE:
                            error = DownloadState.SD_NO_SPACE;
                            break;
                        case DownloadState.SD_NO_USE:
                            error = DownloadState.SD_NO_USE;
                            break;
                        case DownloadState.NO_DATA:
                            error = DownloadState.NO_DATA;
                            break;
                        case DownloadState.SD_SPACE_SMALL:
                        case DownloadState.DATABASE_ERROR_NO:
                        case DownloadState.DATABASE_ERROR_NO_FILE:
                        case DownloadState.NET_ERROR_NO_NET_NO_UPLOAD:
                            error = DownloadState.NO_UPLOAD;
                            break;
                        default:
                            error = DownloadState.OTHER_ERROR;
                            break;
                    }
                    iDownloadCallback.onFailedDownload(downloadInfo, error);
                    break;
                default:
                    break;
            }
        }
    }

    private class ResponseDeliveryRunnableEnumItem implements Runnable {

        private IDownloadCallback iDownloadCallback;
        private CallbackEnum callbackEnum;
        private DownloadInfo downloadInfo;

        public ResponseDeliveryRunnableEnumItem(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum,
                                                DownloadInfo downloadInfo) {
            this.iDownloadCallback = iDownloadCallback;
            this.callbackEnum = callbackEnum;
            this.downloadInfo = downloadInfo;
        }

        @Override
        public void run() {

            // 调用观察者
            switch (callbackEnum) {
                case DID_ADD_DOWNLOAD_ITEM:
                    iDownloadCallback.didAddDownloadItem(downloadInfo);
                    DownloadLog.error("Callback didAddDownloadItem");
                    break;
                case WAIT_START_DOWNLOAD_ITEM:
                    iDownloadCallback.waitStartDownloadItem(downloadInfo);
                    DownloadLog.error("Callback waitStartDownloadItem");
                    break;
                case WILL_START_DOWNLOAD_ITEM:
                    iDownloadCallback.willStartDownloadItem(downloadInfo);
                    DownloadLog.error("Callback willStartDownloadItem");
                    break;
                case DID_START_DOWNLOAD_ITEM:
                    iDownloadCallback.didStartDownloadItem(downloadInfo);
                    DownloadLog.error("Callback didStartDownloadItem");
                    break;
                case WILL_PAUSE_DOWNLOAD_ITEM:
                    iDownloadCallback.willPauseDownloadItem(downloadInfo);
                    DownloadLog.error("Callback willPauseDownloadItem");
                    break;
                case DID_PAUSE_DOWNLOAD_ITEM:
                    iDownloadCallback.didPauseDownloadItem(downloadInfo);
                    DownloadLog.error("Callback didPauseDownloadItem");
                    break;
                case PROGRESS_DOWNLOAD:
                    iDownloadCallback.onProgressDownload(downloadInfo);
                    DownloadLog.error("Callback onProgressDownload");
                    break;
                case FINISHED_DOWNLOAD:
                    iDownloadCallback.onFinishedDownload(downloadInfo);
                    DownloadLog.error("Callback onFinishedDownload");
                    break;
                case WILL_STOP_DOWNLOAD_ITEM:
                    iDownloadCallback.willStopDownloadItem(downloadInfo);
                    DownloadLog.error("Callback willStopDownloadItem");
                    break;
                case DID_STOP_DOWNLOAD_ITEM:
                    iDownloadCallback.didStopDownloadItem(downloadInfo);
                    DownloadLog.error("Callback didStopDownloadItem");
                    break;
                case WILL_DELETE_DOWNLOAD_ITEM:
                    iDownloadCallback.willDeleteDownloadItem(downloadInfo);
                    DownloadLog.error("Callback willDeleteDownloadItem");
                    break;
                case DID_DELETE_DOWNLOAD_ITEM:
                    iDownloadCallback.didDeleteDownloadItem(downloadInfo);
                    DownloadLog.error("Callback didDeleteDownloadItem");
                    break;
                case GET_NEXT_DOWNLOAD_INFO:
                    iDownloadCallback.getNextDownloadInfo(downloadInfo);
                    DownloadLog.error("Callback getNextDownloadInfo");
                    break;
                default:
                    break;
            }
        }
    }

    private class ResponseDeliveryRunnableEnumList implements Runnable {

        private IDownloadCallback iDownloadCallback;
        private CallbackEnum callbackEnum;
        private List<DownloadInfo> list;

        public ResponseDeliveryRunnableEnumList(IDownloadCallback iDownloadCallback, CallbackEnum callbackEnum,
                                                List<DownloadInfo> list) {
            this.iDownloadCallback = iDownloadCallback;
            this.callbackEnum = callbackEnum;
            this.list = list;
        }

        @Override
        public void run() {

            // 调用观察者
            switch (callbackEnum) {
                case INITIALIZATION_SUCCESS:
                    iDownloadCallback.initializationSuccess(list);
                    DownloadLog.error("Callback initializationSuccess");
                    break;
                case ADD_DOWNLOAD_LIST:
                    iDownloadCallback.didAddDownloadList(list);
                    DownloadLog.error("Callback didAddDownloadList");
                    break;
                case DID_PAUSE_DOWNLOAD_LIST:
                    iDownloadCallback.didPauseDownloadList(list);
                    DownloadLog.error("Callback didPauseDownloadList");
                    break;
                case DID_STOP_DOWNLOAD_LIST:
                    iDownloadCallback.didStopDownloadList(list);
                    DownloadLog.error("Callback didStopDownloadList");
                    break;
                case WAIT_START_DOWNLOAD_LIST:
                    iDownloadCallback.waitStartDownloadList(list);
                    DownloadLog.error("Callback waitStartDownloadList");
                    break;
                case DID_DELETE_DOWNLOAD_LIST:
                    iDownloadCallback.didDeleteDownloadList(list);
                    DownloadLog.error("Callback didDeleteDownloadList");
                    break;
                default:
                    break;
            }
        }
    }

}
